1 Wstęp

agencja_nieruchomosci <- read.csv("agencja_nieruchomosci.csv")
knitr::kable(head(agencja_nieruchomosci, 10)) %>%
  kable_styling(font_size = 10)
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
NA 7420 4 2 3 NA no no no yes 2 yes furnished
12250000 8960 4 4 4 yes no no no yes 3 no furnished
12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished
12215000 7500 4 2 2 yes no yes no yes 3 yes furnished
11410000 7420 4 1 2 yes yes yes no yes 2 no furnished
10850000 7500 3 3 1 yes no yes no yes 2 yes semi-furnished
10150000 8580 4 3 4 yes no no no yes 2 yes semi-furnished
10150000 16200 5 3 2 yes no no no no 0 no unfurnished
9870000 8100 4 1 2 yes yes yes no yes 2 yes furnished
9800000 5750 3 2 4 yes yes no no yes 1 yes unfurnished

2 Dane brakujące

2.1 Początkowa liczba i proporcje NA

Ogólne podsumowanie brakujących wartości

knitr::kable(miss_var_summary(agencja_nieruchomosci))
variable n_miss pct_miss
price 110 20.2
mainroad 50 9.17
prefarea 50 9.17
area 0 0
bedrooms 0 0
bathrooms 0 0
stories 0 0
guestroom 0 0
basement 0 0
hotwaterheating 0 0
airconditioning 0 0
parking 0 0
furnishingstatus 0 0

Wprowadzając podstawowe reguły, na przykład weryfikując czy cena nie jest ujemna, mozemy zweryfikować sensowność naszych danych. Po określeniu reguł są one upraszczane. Funkcja simplify_rules pozwala sprawdzić czy nie ma w nich sprzeczności i wyeliminować duplikaty. W tym przypadku wyczyszczenie reguł nie przyniosło zadnych efektów.

rules <- validator(
  price > 0 & price < 100000000,
  area > 0 & area < 100000,
  bedrooms > -1 & bedrooms < 10,
  bathrooms > -1 & bathrooms < 10,
  stories > -1 & stories < 20,
  parking > -1 & parking < 5,
  mainroad %in% c("yes", "no"),
  guestroom %in% c("yes", "no"),
  basement %in% c("yes", "no"),
  hotwaterheating %in% c("yes", "no"),
  airconditioning %in% c("yes", "no"),
  prefarea %in% c("yes", "no"),
  furnishingstatus %in% c(
    "furnished",
    "semi-furnished",
    "unfurnished"
  )
)

warnings()

validation_results <- confront(agencja_nieruchomosci, rules)
knitr::kable(summary(validation_results))
name items passes fails nNA error warning expression
V01 545 435 0 110 FALSE FALSE price > 0 & price < 1e+08
V02 545 545 0 0 FALSE FALSE area > 0 & area < 1e+05
V03 545 545 0 0 FALSE FALSE bedrooms > -1 & bedrooms < 10
V04 545 545 0 0 FALSE FALSE bathrooms > -1 & bathrooms < 10
V05 545 545 0 0 FALSE FALSE stories > -1 & stories < 20
V06 545 545 0 0 FALSE FALSE parking > -1 & parking < 5
V07 545 495 0 50 FALSE FALSE mainroad %vin% c(“yes”, “no”)
V08 545 545 0 0 FALSE FALSE guestroom %vin% c(“yes”, “no”)
V09 545 545 0 0 FALSE FALSE basement %vin% c(“yes”, “no”)
V10 545 545 0 0 FALSE FALSE hotwaterheating %vin% c(“yes”, “no”)
V11 545 545 0 0 FALSE FALSE airconditioning %vin% c(“yes”, “no”)
V12 545 495 0 50 FALSE FALSE prefarea %vin% c(“yes”, “no”)
V13 545 545 0 0 FALSE FALSE furnishingstatus %vin% c(“furnished”, “semi-furnished”, “unfurnished”)
barplot(validation_results, main = "price")

Funkcje summary i barplot zgodnie pokazują ze wszystkie nasze dane mają realne wartości.

Aby ułatwić dalszą pracę można zmienić wartości binarne yes i no na 0 i 1. Wartościom z kolumny furnished nadajemy kolejno wartości 0, 1 i 2 (od unfurnished do furnished).

agencja_nieruchomosci$mainroad <-
  ifelse(agencja_nieruchomosci$mainroad == "yes", 1, 0)
agencja_nieruchomosci$guestroom <-
  ifelse(agencja_nieruchomosci$guestroom == "yes", 1, 0)
agencja_nieruchomosci$basement <-
  ifelse(agencja_nieruchomosci$basement == "yes", 1, 0)
agencja_nieruchomosci$hotwaterheating <-
  ifelse(agencja_nieruchomosci$hotwaterheating == "yes", 1, 0)
agencja_nieruchomosci$airconditioning <-
  ifelse(agencja_nieruchomosci$airconditioning == "yes", 1, 0)
agencja_nieruchomosci$prefarea <-
  ifelse(agencja_nieruchomosci$prefarea == "yes", 1, 0)

agencja_nieruchomosci$furnishingstatus <- ifelse(
  agencja_nieruchomosci$furnishingstatus == "unfurnished",
  0,
  ifelse(
    agencja_nieruchomosci$furnishingstatus == "semi-furnished",
    1,
    2
  )
)
knitr::kable(head(agencja_nieruchomosci, 10)) %>%
  kable_styling(font_size = 10)
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
NA 7420 4 2 3 NA 0 0 0 1 2 1 2
12250000 8960 4 4 4 1 0 0 0 1 3 0 2
12250000 9960 3 2 2 1 0 1 0 0 2 1 1
12215000 7500 4 2 2 1 0 1 0 1 3 1 2
11410000 7420 4 1 2 1 1 1 0 1 2 0 2
10850000 7500 3 3 1 1 0 1 0 1 2 1 1
10150000 8580 4 3 4 1 0 0 0 1 2 1 1
10150000 16200 5 3 2 1 0 0 0 0 0 0 0
9870000 8100 4 1 2 1 1 1 0 1 2 1 2
9800000 5750 3 2 4 1 1 0 0 1 1 1 0

Brakujące wartości wg. stanu umeblowania

agencja_nieruchomosci %>%
  group_by(furnishingstatus) %>%
  miss_var_summary() %>%
  filter(n_miss > 0) %>%
  knitr::kable()
furnishingstatus variable n_miss pct_miss
2 price 33 23.6
2 prefarea 15 10.7
2 mainroad 11 7.86
1 price 43 18.9
1 mainroad 23 10.1
1 prefarea 18 7.93
0 price 34 19.1
0 prefarea 17 9.55
0 mainroad 16 8.99
agencja_nieruchomosci %>%
  miss_case_table() %>%
  knitr::kable()
n_miss_in_case n_cases pct_cases
0 363 66.6055046
1 155 28.4403670
2 26 4.7706422
3 1 0.1834862

W tabeli podsumowującej widzimy, że liczba pustych pól na obserwację waha się od 0 do 7. Spośród 545 obserwacji 363 jest kompletnych - to 66,6% obserwacji w danych. Tylko 1 obserwacja (0,18%) zawiera 3 brakujące wartości.

2.2 Wizualizacja NA

vis_miss(agencja_nieruchomosci)

gg_miss_fct(agencja_nieruchomosci, fct=furnishingstatus)

gg_miss_fct(agencja_nieruchomosci, fct=stories)

gg_miss_fct(agencja_nieruchomosci, fct=parking)

Dzięki wykresom, które przedstawiają procent brakujących danych w zależności od filtru można wywnioskować, że największy procent brakujących danych jest zazwyczaj w momencie, gdzie jest najwieksza wartość dodatnia z konkretnych filtrów. Przykładowo największa ilość NA (price) jest w momencie, gdzie są 3 miejsca parkingowe.

2.3 Przekroje NA

gg_miss_upset(agencja_nieruchomosci, nsets=3)

Na powyższym wykresie widać, że najwięcej brakujących danych jest w kolumnie cena. Przyczyny są prawdopodobnie czysto praktycznie - za wysoka cena może odstraszyć potencjalnych klientów. Potencjalną przyczyną może oznaczać chęć zbierania ofert.

2.4 Zależności pomiędzy brakującymi danymi.

ggplot(data = agencja_nieruchomosci, aes(x = area, y = price)) +
  geom_point() +
  geom_miss_point() +
  scale_color_manual(values = c("darkorange", "cyan4")) +
  theme_minimal()

W pierwszym przypadku widzimy, że brak wartości price był podobnie prawdopodobny do większości przypadków powierzchni domu. Można zauważyć brak NA w wielkości domu od 12 tys. do 16 tys. jednak są tam tylko pojedyncze wartości.

ggplot(data = agencja_nieruchomosci, aes(x = area, y = price)) +
  geom_point() +
  geom_miss_point() +
  scale_color_manual(values = c("darkorange", "cyan4")) +
  theme_minimal() +
  facet_wrap(~bedrooms)

W podziale na podwykresy widzimy, że najwięcej NA znajduje sie w nieruchomościach, które mają 3 sypialnie.

3 Czyszczenie danych

3.1 Imputacje danych

Identyfikacja brakujących danych jest kluczowym elementem czyszczenia datasetu. Kolejnym krokiem jest imputacja, czyli uzupełnienie brakujących komórek. Jest wiele metod umożliwiających imputację. Jedną z najpopularniejszych metod jest algorytm k najbliższych sąsiadów (kNN). Poniżej wykorzystano tę metodę to uzupełnienia brakujących cen. Niezbędnym jest tutaj określenie ilości sąsiadów (k) branych pod uwagę przy regresji, arbitralnie wybrana została wartość k=15.

agencja_nieruchomosci <- kNN(
  agencja_nieruchomosci,
  variable = "price",
  k = 15
)
agencja_nieruchomosci <- subset(agencja_nieruchomosci, select = -price_imp)
knitr::kable(miss_var_summary(agencja_nieruchomosci))
variable n_miss pct_miss
mainroad 50 9.17
prefarea 50 9.17
price 0 0
area 0 0
bedrooms 0 0
bathrooms 0 0
stories 0 0
guestroom 0 0
basement 0 0
hotwaterheating 0 0
airconditioning 0 0
parking 0 0
furnishingstatus 0 0

Kolejną znaną metodą jest imputacja liniowa. Zmienne brakujące w kolumnie mainroad uzupełnione zostały wykorzystując metodę impute_lm pochodzącą z pakietu simputation. Wartości te imputujemy na podstawie zmiennych price oraz parking.

agencja_nieruchomosci <- impute_lm(
  agencja_nieruchomosci,
  variable = "mainroad",
  formula = mainroad ~ price + parking,
)
agencja_nieruchomosci$mainroad <- round(agencja_nieruchomosci$mainroad)

knitr::kable(miss_var_summary(agencja_nieruchomosci))
variable n_miss pct_miss
prefarea 50 9.17
price 0 0
area 0 0
bedrooms 0 0
bathrooms 0 0
stories 0 0
mainroad 0 0
guestroom 0 0
basement 0 0
hotwaterheating 0 0
airconditioning 0 0
parking 0 0
furnishingstatus 0 0

Dane w ostatniej brakującej kolumnie uzupełniamy metodą mice czyli Multivariate Imputation by Chained Equations - wielowymiarowe wypełnianie przez równania łańcuchowe. Jako że uzupełniamy zmienną binarną, korzystamy z metody logreg.

imputed_data <- mice(agencja_nieruchomosci, method = "logreg", m = 5, printFlag = FALSE)
completed_data <- complete(imputed_data, 1)
agencja_nieruchomosci <- completed_data

Zobaczmy jak wygląda pierwsze 10 wierszy naszego zbioru danych po imputacji:

knitr::kable(head(agencja_nieruchomosci, 10)) %>%
  kable_styling(font_size = 10)
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
7910000 7420 4 2 3 1 0 0 0 1 2 1 2
12250000 8960 4 4 4 1 0 0 0 1 3 0 2
12250000 9960 3 2 2 1 0 1 0 0 2 1 1
12215000 7500 4 2 2 1 0 1 0 1 3 1 2
11410000 7420 4 1 2 1 1 1 0 1 2 0 2
10850000 7500 3 3 1 1 0 1 0 1 2 1 1
10150000 8580 4 3 4 1 0 0 0 1 2 1 1
10150000 16200 5 3 2 1 0 0 0 0 0 0 0
9870000 8100 4 1 2 1 1 1 0 1 2 1 2
9800000 5750 3 2 4 1 1 0 0 1 1 1 0

## Transformacje


``` r
completed_data$price <- as.numeric(completed_data$price)
completed_data <- completed_data %>%
  mutate(
    price_z = (price - mean(price, na.rm = TRUE)) / sd(price, na.rm = TRUE),
    price_minmax = scales::rescale(price, to = c(0, 1))
  )
boxplot(completed_data$price_z, completed_data$price_minmax,
        names = c("Z-score", "Min-max"), main = "Porównanie normalizacji danych")

skewness_results <- sapply(completed_data, function(x) if (is.numeric(x)) e1071::skewness(x, na.rm = TRUE) else NA)
knitr::kable(skewness_results)
x
price 1.2284480
area 1.3139246
bedrooms 0.4929587
bathrooms 1.5805260
stories 1.0761391
mainroad -2.2903089
guestroom 1.6791359
basement 0.6251337
hotwaterheating 4.3294938
airconditioning 0.7913726
parking 0.8374328
prefarea 1.2236374
furnishingstatus 0.1170196
price_z 1.2284480
price_minmax 1.2284480

3.2 Obserwacje odstające

outlier_report <- diagnose_outlier(completed_data)
knitr::kable(outlier_report)
variables outliers_cnt outliers_ratio outliers_mean with_mean without_mean
price 13 2.3853211 1.053123e+07 4.721686e+06 4.579723e+06
area 12 2.2018349 1.269325e+04 5.150541e+03 4.980724e+03
bedrooms 12 2.2018349 5.166667e+00 2.965138e+00 2.915572e+00
bathrooms 1 0.1834862 4.000000e+00 1.286239e+00 1.281250e+00
stories 41 7.5229358 4.000000e+00 1.805505e+00 1.626984e+00
mainroad 67 12.2935780 0.000000e+00 8.770642e-01 1.000000e+00
guestroom 97 17.7981651 1.000000e+00 1.779817e-01 0.000000e+00
basement 0 0.0000000 NaN 3.504587e-01 3.504587e-01
hotwaterheating 25 4.5871560 1.000000e+00 4.587160e-02 0.000000e+00
airconditioning 0 0.0000000 NaN 3.155963e-01 3.155963e-01
parking 12 2.2018349 3.000000e+00 6.935780e-01 6.416510e-01
prefarea 130 23.8532110 1.000000e+00 2.385321e-01 0.000000e+00
furnishingstatus 0 0.0000000 NaN 9.302752e-01 9.302752e-01
price_z 13 2.3853211 3.269696e+00 0.000000e+00 -7.989860e-02
price_minmax 13 2.3853211 8.363077e-01 2.830177e-01 2.694975e-01
dane <- (agencja_nieruchomosci)
Q1 <- quantile(dane$stories, 0.25, na.rm = TRUE)
Q3 <- quantile(dane$stories, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1

lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
outliers <- dane$stories[dane$stories < lower_bound | dane$stories > upper_bound]

boxplot(dane$stories, main = "Wartości odstające w zmiennej 'stories'",
        col = "lightblue", horizontal = TRUE)

dane_cleaned <- dane %>%
  filter(stories >= lower_bound, stories <= upper_bound)

boxplot(dane_cleaned$stories, main = "wykres pudełkowy dla zmiennej 'stories' bez wartości odstających",
        col = "lightblue", horizontal = TRUE)

Wykres pudełkowy dla zmiennej “stories” bez wartości odstających - został nałożony filtr nieuwzględniający wartości odstających.

4 Wizualizacja danych

completed_data$price <- completed_data$price / 1000
completed_data$area <- completed_data$area * 0.092903
ggplot(completed_data, aes(x=price))+
  geom_histogram(bins = 10)+
  labs(title="Ilośc domów z przedziałami cenowymi", x="Price", y="Ilość domów")+
  theme_bw() +
  facet_grid(~parking)

4.1 Zależność ceny od wielkości domu w podziale na połaczenie do głównej drogi

completed_data$bedfac <- as.factor(completed_data$bedrooms)

ggplot(completed_data, aes(x = area, y = price, color = bedfac)) +
  geom_point(alpha = 0.7, size = 3) +
  scale_color_brewer(palette = "Set1") +
  theme_ipsum() +
  facet_grid(~mainroad) +
  labs(
    x = "Wielkość domu",
    y = "Cena",
    color = "Liczba sypialni")+
  theme( text = element_text(family = "sans"))

4.2 Zależność ceny od sypialni z podziałem na “prefarea”

ggplot(completed_data, aes(x = bedrooms, y = price, color = bedfac)) +
  geom_point(alpha = 0.7, size = 3) +
  scale_color_brewer(palette = "Set1") +
  theme_ipsum() +
  theme(
    text = element_text(family = "sans")  ## Użyj czcionki sans
  ) +
  facet_grid(~prefarea) +
  labs(
    x = "ilość sypialni",
    y = "Cena",
    color = "Liczba sypialni"
  )

4.3 wykres ceny w zaleznosci od metrazu

completed_data$prefarea1 <- as.factor(completed_data$prefarea)  ## Zamiana na factor

p <- ggplot(completed_data, aes(x = price, y = area)) +
  geom_point(aes(color = prefarea1)) +  
  geom_smooth(method = "lm", se = TRUE)+
  xlab("Cena")+
  ylab("Powierzchnia domu")+
  scale_color_discrete(name = "Preferowane miejsce")+
  ggtitle("Metraż oraz cena domu")+
  theme_light()

plotly::ggplotly(p)

4.4 Rozkład powierzchni domu w zależności od liczby pięter

completed_data$pietra <- as.factor(completed_data$stories)

ggplot(completed_data, aes(x = stories, y = area)) +
  geom_boxplot(aes(group = stories), outlier.shape = NA) + 
  geom_jitter(aes(color = price), width = 0.2, alpha = 0.7) +
  scale_color_gradient(name = "Cena", low = "lightblue", high = "navyblue") +
  xlab("Liczba pięter") +
  ylab("Powierzchnia domu") +
  ggtitle("Rozkład powierzchni domu w zależności od liczby pięter i ceny") +
  theme_minimal()

summary_table <- completed_data %>%
  group_by(pietra) %>%
  summarise(
    Srednia_powierzchnia = mean(area, na.rm = TRUE),
    Mediana_powierzchnia = median(area, na.rm = TRUE),
    Std_powierzchnia = sd(area, na.rm = TRUE),
    Srednia_cena = mean(price, na.rm = TRUE),
    Mediana_cena = median(price, na.rm = TRUE),
    Std_cena = sd(price, na.rm = TRUE),
    Liczba_obserwacji = n()
  )
knitr::kable(summary_table)
pietra Srednia_powierzchnia Mediana_powierzchnia Std_powierzchnia Srednia_cena Mediana_cena Std_cena Liczba_obserwacji
1 491.4405 418.0635 211.4452 4155.658 3815 1367.579 227
2 441.9345 386.9410 197.1835 4723.147 4200 1841.284 238
3 493.9319 510.9665 183.7000 5451.385 5810 1289.063 39
4 604.4428 557.4180 111.2456 7152.962 7245 1518.262 41

4.5 Kategoryzacja cen poprzez średnią i odchylenie standardowe

mean_price <- mean(completed_data$price)
sd_price <- sd(completed_data$price)

completed_data$z_score <- (completed_data$price - mean_price) / sd_price

completed_data$price_category <- cut(
  completed_data$z_score,
  breaks = c(-Inf, -1, 1, Inf),
  labels = c("tanie", "średnie", "drogie")
)

category_counts <- completed_data %>%
  group_by(price_category) %>%
  summarise(count = n())

4.6 Rozkład cen na kategorie: tani, średni i drogi

Wykres przedstawia ceny nieruchomości, które należą do agencji nieruchomości. Poprzez stworzenie 3 znaczników - tani, średni, drogi możemy przeanalizować w jaki sposób plasują się ceny z bazy danych.

ggplot(category_counts) +
  aes(
    x0 = 0, y0 = 0,
    r0 = 0, r = 1,
    amount = count,
    fill = price_category
  ) +
  geom_arc_bar(stat = "pie") +
  coord_fixed()

etykiety<-c("1750-2750 kPLN","2750-3750 kPLN","3750-4750 kPLN","4750-5750 kPLN","5750-6750 kPLN","6750-7750 kPLN","7750-8750 kPLN","9750-10750 kPLN","10750-11750 kPLN","11750-12250 kPLN")
limits<-cut(completed_data$price,seq(1750,12250,by=1000),labels=etykiety)
tabela1<-freq(limits)
knitr::kable(tabela1)
n % val%
1750-2750 kPLN 35 6.4 6.5
2750-3750 kPLN 145 26.6 26.9
3750-4750 kPLN 146 26.8 27.1
4750-5750 kPLN 87 16.0 16.1
5750-6750 kPLN 66 12.1 12.2
6750-7750 kPLN 24 4.4 4.5
7750-8750 kPLN 21 3.9 3.9
9750-10750 kPLN 8 1.5 1.5
10750-11750 kPLN 5 0.9 0.9
11750-12250 kPLN 2 0.4 0.4
NA 6 1.1 NA

4.7 Statystyka opisowa

Poniższy wykres kolumnowy przedstawia rozkład cen mieszkań z podziałem co 1000. Można wywnioskować, iż tak jak na wykresie kołowym, większość mieszkań jest blisko średniej ceny rynkowej. Tańsze mieszkania oraz droższe są w zdecydowanej mniejszości. Dodatkowo zaznaczono liniami jak kształtują się ceny mieszkań w podziale na ilość sypialni.

hist(completed_data$price, breaks="FD", col="green", probability = TRUE,
     main="Ceny nieruchomości")

lines(density(completed_data$price[completed_data$bedrooms == 1]), col=2)
lines(density(completed_data$price[completed_data$bedrooms == 2]), col=3)
lines(density(completed_data$price[completed_data$bedrooms == 3]), col=4)

legend("topright", 
       legend=c("Jedna sypialnia", "Dwie sypialnie", "Trzy sypialnie"),
       col=c(2, 3, 4), 
       lty=1, 
       horiz=FALSE, 
       box.lty=0, 
       cex=0.8)

completed_data %>%
  select(price, bedfac) %>%
  tbl_summary(
    by=bedfac,
    type = all_continuous() ~ "continuous2",
    statistic = all_continuous() ~ c(
      "{N_nonmiss}","{mean}","{sd}",
      "{median} ({p25}, {p75})",
      "{min}, {max}"),
    missing = "no",
    label = price ~ "Cena") %>%
  modify_header(label ~ "**Zmienna**") %>%
  modify_caption("**Tabela 1. Rozkład cen wg liczby pokoi**") %>%
  bold_labels() %>% 
  add_p(pvalue_fun = ~ style_pvalue(.x, digits = 2))
Tabela 1. Rozkład cen wg liczby pokoi
Zmienna 1
N = 2
2
N = 136
3
N = 300
4
N = 95
5
N = 10
6
N = 2
p-value
Cena






    N Non-missing 2 136 300 95 10 2
    Mean 2,713 3,647 4,919 5,551 5,925 4,792
    SD 619 990 1,678 2,147 2,339 1,826
    Median (Q1, Q3) 2,713 (2,275, 3,150) 3,500 (2,951, 4,200) 4,550 (3,640, 5,950) 5,250 (4,060, 6,300) 5,583 (3,850, 8,120) 4,792 (3,500, 6,083)
    Min, Max 2,275, 3,150 1,750, 7,070 1,750, 12,250 2,100, 12,250 3,010, 10,150 3,500, 6,083

4.8 Wykres wiolinowy

Podstawowe statystyki opisowe cen nieruchomości jeżeli znajdują się w preferowanym obszarze (tak/nie - 1/0). Dla obu przypadków są widoczne obserwacje odstające dla zmiennej price. Mediana cen nieruchomości dla tych znajdujących się w preferowanej okolicy jest większa. W bazie więcej jest nieruchomości, które nie znajdują sie w preferowanej okolicy. W przypadku nieruchomości nieznajdujących się w preferowanym obszarze, pierwsza część obserwacji ma większe zagęszczenie przy niskiej cenie 2 - 4 tys., a ceny nad medianą mają większą rozpiętość - od około 4 do 12 tys. Dla nieruchomości w preferowanym obszarze wiolina jest najszersza w okolicach mediany - najwięcej obserwacji kiedy cena jest bliska wartości środkowej - około 6 tys.

data(completed_data)

completed_data %>%
  filter(prefarea %in% c(0, 1))%>%
  ggbetweenstats(
    y=price,
    x=prefarea
  )

## Wykres kołowy Jaki procent nieruchomości o powierzchni z danego przedziału posiada posiada wskazaną liczbę łazienek. Nawet w domach o największej powierzni jest tylko jedna łazienka.

completed_data$area_category <- cut(
  completed_data$area, 
  breaks = c(0, 2000, 5000, 10000, 16200),
  labels = c("0-2000", "2001-5000", "5001-10000", "10001-1620"),
  right = TRUE
)

completed_data %>%
  filter(bathrooms %in% c(1, 2 ,3, 4))%>%
  ggpiestats(
    y=area_category,
    x=bathrooms
  )

4.9 Korelogram

Korelogram przedstawiający korelację pomiędzy zmiennymi dla domów z dwoma i sześcioma sypialniami z podziałem na dwie grupy - czy znajdują się przy głównej ulicy (1), czy nie (0).

grouped_ggcorrmat(
  data         = dplyr::filter(completed_data, bedrooms %in% c(2,6)),
  type         = "robust",
  colors       = c("#cbac43", "white", "#550000"),
  grouping.var = mainroad,
  matrix.type  = "lower"
)

5 Podsumowanie i wnioski